package cn.yrec.rain.analysis.service.impl;

import cn.hutool.core.util.NumberUtil;
import cn.yrec.rain.analysis.mappers.BasinHyMapper;
import cn.yrec.rain.analysis.model.BasinHy;
import cn.yrec.rain.analysis.model.HyQHourRt;
import cn.yrec.rain.analysis.model.vo.HydFlowAndQsResult;
import cn.yrec.rain.analysis.model.vo.HystResult;
import cn.yrec.rain.analysis.model.vo.region.RegionDataItemVo;
import cn.yrec.rain.analysis.model.vo.region.RegionDataVo;
import cn.yrec.rain.analysis.service.HyQHourRtService;
import cn.yrec.rain.analysis.service.HydDataService;
import cn.yrec.rain.analysis.service.RemoteApiService;
import cn.yrec.rain.analysis.utils.DateUtils;
import cn.yrec.rain.analysis.utils.NumberUtils;
import cn.yrec.rain.analysis.vo.HydDataRequestParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 描述:
 *  水文站信息的查询服务接口实现类
 * @createDate: 2023/05/30 17:22
 * @author: yanglichen
 */
@Service
public class HydDataServiceImpl implements HydDataService {

    @Autowired
    private BasinHyMapper basinHyMapper;
    @Autowired
    private HyQHourRtService hyQHourRtService;
    @Autowired
    private RemoteApiService remoteApiService;


    @Override
    public List<HystResult> getByBasinNameListAndTime(HydDataRequestParam param) {
        List<HystResult> result = new ArrayList<>();
        List<String> basinNameList = param.getBasinNameList();
        Date startTime = param.getStartTime();
        Date endTime = param.getEndTime();
        for (String basinName : basinNameList) {
            HystResult hystResult = calculateResultByBasinNameAndDate(basinName, startTime, endTime);
            if (hystResult != null) {
                result.add(hystResult);
            }
        }
        return result;
    }

    /**
     * 方法描述: 根据流域对象获取站码列表
     * @author yanglichen
     * @date 2023-05-30 18:12
     * @param hyList 水文站站码列表
     **/
    private List<String> getHydStcdListByBasinHyList(List<BasinHy> hyList) {
        List<String> stcdList = new ArrayList<>();
        for (BasinHy item : hyList) {

            String ctrStcd = item.getCtrStcd();
            String mainStcd = item.getMainStcd();
            String nextStcd = item.getNextStcd();
            String otherStcd = item.getOtherStcd();

            if (ctrStcd != null) stcdList.add(ctrStcd);
            if (mainStcd != null) stcdList.add(mainStcd);
            if (nextStcd != null) stcdList.add(nextStcd);
            if (otherStcd != null) stcdList.add(otherStcd);
        }
        return stcdList;
    }


    /**
     * 方法描述: 通过流域名称获取关键站数据对象
     * @author yanglichen
     * @date 2023-05-30 18:01
     * @param basinNameList 流域名称列表
     **/
    private List<BasinHy> getByBasinNameList(List<String> basinNameList) {
        List<BasinHy> result = new ArrayList<>();
        for (String basinName : basinNameList) {
            BasinHy byBasinName = basinHyMapper.findByBasinName(basinName);
            if (byBasinName != null) {
                // 封装流域名称
                byBasinName.setBasinName(basinName);
                result.add(byBasinName);
            }
        }
        return result;
    }

    /**
     * 方法描述: 根据水文站的站码和起始时间得到这个水文站的洪沙特性
     *
     * @param result 洪沙特征值实例
     * @author yanglichen
     * @date 2020-08-28 18:51
     **/
    private void calculateEntity(HydFlowAndQsResult result) {
        if (result.getStcd() == null) {
            return;
        }
        String stcd = result.getStcd();
        Date startDate = result.getStartDate();
        Date endDate = result.getEndDate();
        //根据站码列表查询水文站小时表信息
        List<HyQHourRt> hyQHourRtList = hyQHourRtService.findByStcdAndDate(stcd, startDate, endDate);
        // 手动对河道水情的结果进行去重处理
        hyQHourRtList = distinctDateHyQHourRtList(hyQHourRtList);
        if (hyQHourRtList.size() == 0) {
            return;
        }
        //得到最大流量实例
        HyQHourRt maxFlowEntity = hyQHourRtService.getMaxFlowEntity(hyQHourRtList);
        //最大流量
        double maxFlow = maxFlowEntity.getFlow();
        Date maxFlowTime = maxFlowEntity.getDate();

        //得到最大泥沙实例
        HyQHourRt maxQsEntity = hyQHourRtService.getMaxQsEntity(hyQHourRtList);
        double maxQs = 0;
        Date maxQsTime = null;
        if (maxQsEntity != null) {
            //最大泥沙
            maxQs = maxQsEntity.getQs();
            maxQsTime = maxQsEntity.getDate();
        }
        //总水量(亿m³)
        double totalQ = hyQHourRtService.getTotalQ(hyQHourRtList);
        //总含沙量(吨)
        double totalQs = hyQHourRtService.getTotalQs(hyQHourRtList);
        //水文站时段流量
        Map<String, Object> dateFlowList = hyQHourRtService.getTimeFlow(hyQHourRtList);
        //水文站时段含沙量
        Map<String, Object> dateQsList = hyQHourRtService.getTimeQs(hyQHourRtList);
        // 封装名字
        dateFlowList.put("name", result.getStnm());
        // 封装名字
        dateQsList.put("name", result.getStnm());

        //封装结果
        result.setStcd(stcd);
        result.setStartDate(startDate);
        result.setEndDate(endDate);
        result.setMaxFlow(maxFlow);
        result.setMaxFlowTime(maxFlowTime);
        result.setMaxQs(maxQs);
        result.setMaxQsTime(maxQsTime);
        result.setTotalQ(totalQ);
        result.setTotalQs(totalQs);

        result.setDateFlowList(dateFlowList);
        result.setDateQsList(dateQsList);

        if (result.getMaxFlow() != null) {
            result.setMaxFlow(NumberUtils.round(result.getMaxFlow(), 2));
        }
        if (result.getTotalQ() != null) {
            result.setTotalQ(NumberUtils.round(result.getTotalQ(), 2));
        }
        if (result.getMaxQs() != null) {
            result.setMaxQs(NumberUtils.round(result.getMaxQs(),2));
        }
        if (result.getTotalQs() != null) {
            result.setTotalQs(NumberUtils.round(result.getTotalQs(), 2));
        }
    }

    /**
     * 方法描述: 根据时间对象去重处理
     * @author yanglichen
     * @date 2023-06-02 08:42
     * @param hyQHourRtList 原始对象
     * @return 去重对象
     **/
    private List<HyQHourRt> distinctDateHyQHourRtList(List<HyQHourRt> hyQHourRtList) {
        // 构造有序的Map的对象
        LinkedHashMap<Date, HyQHourRt> linkedHashMap = new LinkedHashMap<>();
        // 遍历序列对象
        for (HyQHourRt item : hyQHourRtList) {
            Date itemDate = item.getDate();
            linkedHashMap.put(itemDate, item);
        }
        // LinkedHashMap转换成List对象
        Collection<HyQHourRt> values = linkedHashMap.values();
        return new ArrayList<>(values);
    }

    /**
     * 方法描述: 根据流域名,开始时间和结束时间得到相关的流量信息和泥沙特性
     *
     * @param basinName 流域名
     * @param startDate 开始时间
     * @param endDate   结束时间
     * @return 流量信息和泥沙特性
     * @author yanglichen
     * @date 2020-08-24 23:00
     **/
    public HystResult calculateResultByBasinNameAndDate(String basinName, Date startDate, Date endDate) {
        //构造结果集
        HystResult result = new HystResult();
        /*处理结束时间
         * 如果结束时间+5天之后不到今天
         * 那么就可以加5天,否则就加到今天
         */
        long nowTimes = new Date().getTime();
        long tempTime = endDate.getTime();
        long tempDate = (nowTimes - tempTime) / DateUtils.ONE_DAY_MILLI_SECOND;
        //判断结束时间距离现在的时间
        if (tempDate <= 5) {
            endDate = new Date(nowTimes);
        } else {
            endDate = new Date(tempTime + 5 * DateUtils.ONE_DAY_MILLI_SECOND);
        }
        result.setBasinName(basinName);
        List<HydFlowAndQsResult> hydList = getHydListByRegionName(basinName);
        for (HydFlowAndQsResult item : hydList) {
            item.setStartDate(startDate);
            item.setEndDate(endDate);
            calculateEntity(item);
        }
        result.setHydList(hydList);
        List<String> timeZone = DateUtils.getTimeZoneByStartDayAndEndDayFirstBigDate(startDate, endDate);
        result.setTimeZone(timeZone);
        return result;
    }


    /**
     * 方法描述:
     *  根据流域名称获得水文站对象站码列表
     * @author yanglichen
     * @date 2023-06-09 15:59
     * @param regionName 流域名称
     **/
    private List<HydFlowAndQsResult> getHydListByRegionName(String regionName) {
        List<HydFlowAndQsResult> result = new ArrayList<>();
        // 构造去重数据集
        LinkedHashSet<HydFlowAndQsResult> hashSet = new LinkedHashSet<>();
        RegionDataVo item = remoteApiService.getRegionObjByRegionName(regionName);
        if (item == null) {
            return result;
        }
        List<RegionDataItemVo> tributaryHydroStations = item.getTributaryHydroStations();
        RegionDataItemVo trunkHydroStation = item.getTrunkHydroStation();

        // 数据非空判断
        boolean hasTributary = !(tributaryHydroStations == null || tributaryHydroStations.size() == 0);
        // 数据非空判断
        boolean hasTrunk = !(trunkHydroStation == null);

        if (hasTributary) {
            for (RegionDataItemVo itemVo : tributaryHydroStations) {
                HydFlowAndQsResult hydItem = new HydFlowAndQsResult();
                hydItem.setBasinName(regionName);
                hydItem.setStcd(itemVo.getStcd());
                hydItem.setStnm(itemVo.getStnm());
                hashSet.add(hydItem);
            }
        }
        if (hasTrunk) {
            HydFlowAndQsResult hydItem = new HydFlowAndQsResult();
            hydItem.setBasinName(regionName);
            hydItem.setStcd(trunkHydroStation.getStcd());
            hydItem.setStnm(trunkHydroStation.getStnm());
            hashSet.add(hydItem);
        }
        // 对数据进行去重
        result.addAll(hashSet);
        return result;
    }
}
